//
//  MKUIWaterFlowLayoutConstraint.h
//  MKUI
//  瀑布流布局，一行放不下时，会另起一行。行内元素间间隔固定，行间间隔也固定。
//  瀑布流规则：每个元素通过sizeThatFits方法，返回在当前行剩余空间下，自己需要的尺寸。如果剩余空间小于sizeThatFits返回值，则将另起一行显示。
/// 添加行数限制，以及最后一行，优先布局指定元素。应用场景如：在搜索历史展示，只展示前2行，且第2行末尾展示"展开/折叠"按钮。折叠时，限制2行，展开时，可以设置为限制99999999行。
//  Created by 苏尚进 on 2023/2/17.
//  Copyright © 2023 moon. All rights reserved.
//

#import "MKUILayoutConstraint.h"

NS_ASSUME_NONNULL_BEGIN

@interface MKUIWaterFlowLayoutConstraint : MKUILayoutConstraint
@property(nonatomic,assign) MKUILayoutConstraintDirection layoutDirection;//布局方向.默认为MKUILayoutConstraintDirectionHorizontal
@property(nonatomic,assign) MKUILayoutConstraintVerticalAlignment layoutVerticalAlignment;//所有元素作为一个整体,在垂直方向上的位置,以及每一个元素在整体内的垂直方向上的对齐方式.默认为MKUILayoutConstraintVerticalAlignmentCenter

@property(nonatomic,assign) MKUILayoutConstraintHorizontalAlignment layoutHorizontalAlignment;//所有元素作为一个整体,在水平方向上的位置,以及每一个元素在整体内的水平方向上的对方方式.默认为MKUILayoutConstraintHorizontalAlignmentCenter
@property(nonatomic,assign) UIEdgeInsets contentInsets;//内边距,默认为(0,0,0,0)
@property(nonatomic,assign) CGFloat interitemSpacing;//平行layoutDirection方向上元素间的间隔,默认为0
@property(nonatomic,assign) CGFloat lineSpacing;//垂直layoutDirection方向上，元素间的间隔,默认为0

@property(nonatomic,readonly,nullable) MKUILayoutConstraintItemAttributeSection *itemAttributeSection;

/// 计算最合适的尺寸
/// @param size 外层限制
/// @param resizeItems 是否计算子元素的最合适尺寸。YES：调用子元素的sizeThatFits方法。NO：直接使用子元素的bounds.size
- (CGSize)sizeThatFits:(CGSize)size resizeItems:(BOOL)resizeItems;

/// 对子元素进行布局
/// @param resizeItems 在布局前,是否让每个子元素自动调整到合适的尺寸
- (void)layoutItemsWithResizeItems:(BOOL)resizeItems;

/// 计算在限制的容器尺寸下，生成布局每行的元素情况（水平布局为行数，垂直布局为列数）。里面每个元素只是计算了size值，origin都为(0,0)
/// @param size 容器尺寸
/// @param resizeItems 在布局前,是否让每个子元素自动调整到合适的尺寸
- (nullable MKUILayoutConstraintItemAttributeSection *)itemAttributeSectionThatFits:(CGSize)size resizeItems:(BOOL)resizeItems;


/// 在瀑布流布局的基础上，添加上行数限制。具体为超出上限的行，不展示。同时固定最后一行末尾元素为lastLineItem，且该元素优先布局。
/// 这种布局可以用在app的搜索历史列表，末尾添加上一个“展开/折叠"的按钮(=lastLineItem)，同时折叠起来时，只展示N行。
#pragma mark - limit max lines
@property(nonatomic,assign) NSInteger maxLines;//限制最大的行数（水平布局时为行数，垂直布局时为列数)，<=0代表不限。超过该行数，后续元素尺寸都设置为(0,0)
@property(nonatomic,strong,nullable) id<MKUILayoutConstraintItemProtocol> lastLineItem;//最后一行固定在末尾的item。如果有值，最后一行布局时，每一个元素都将扣除该末尾元素的空间，保证末尾元素一定显示。
@property(nonatomic,assign) BOOL showLastLineItemWithinMaxLine;//当maxLines>0且行数在最大值之内时，是否显示lastLineItem
@property(nonatomic,readonly) BOOL overMaxLines;//当maxLines>0时，行数是否超出行上限
@end

NS_ASSUME_NONNULL_END


NS_ASSUME_NONNULL_BEGIN
typedef enum : NSUInteger {
    MKUIWaterFlowLayoutConstraintParam_H_C_C,
    MKUIWaterFlowLayoutConstraintParam_H_C_L,
    MKUIWaterFlowLayoutConstraintParam_H_C_R,
    MKUIWaterFlowLayoutConstraintParam_H_T_C,
    MKUIWaterFlowLayoutConstraintParam_H_T_L,
    MKUIWaterFlowLayoutConstraintParam_H_T_R,
    MKUIWaterFlowLayoutConstraintParam_H_B_L,
    MKUIWaterFlowLayoutConstraintParam_H_B_C,
    MKUIWaterFlowLayoutConstraintParam_H_B_R,
    MKUIWaterFlowLayoutConstraintParam_V_C_C,
    MKUIWaterFlowLayoutConstraintParam_V_C_L,
    MKUIWaterFlowLayoutConstraintParam_V_C_R,
    MKUIWaterFlowLayoutConstraintParam_V_T_C,
    MKUIWaterFlowLayoutConstraintParam_V_T_L,
    MKUIWaterFlowLayoutConstraintParam_V_T_R,
    MKUIWaterFlowLayoutConstraintParam_V_B_C,
    MKUIWaterFlowLayoutConstraintParam_V_B_L,
    MKUIWaterFlowLayoutConstraintParam_V_B_R,
} MKUIWaterFlowLayoutConstraintParam;

MKAS_EnumTypeCategories(MKUIWaterFlowLayoutConstraintParam)
@interface MKUIWaterFlowLayoutConstraint(InitMethod)
- (id)initWithItems:(nullable NSArray<id<MKUILayoutConstraintItemProtocol>> *)items constraintParam:(MKUIWaterFlowLayoutConstraintParam)param contentInsets:(UIEdgeInsets)contentInsets interitemSpacing:(CGFloat)interitemSpacing lineSpacing:(CGFloat)lineSpacing;
- (void)configWithConstraintParam:(MKUIWaterFlowLayoutConstraintParam)param;
@property(nonatomic,assign) MKUIWaterFlowLayoutConstraintParam constraintParam;

+ (void)parseConstraintParam:(MKUIWaterFlowLayoutConstraintParam)param layoutDirection:(MKUILayoutConstraintDirection *)layoutDirection layoutVerticalAlignment:(MKUILayoutConstraintVerticalAlignment *)layoutVerticalAlignment layoutHorizontalAlignment:(MKUILayoutConstraintHorizontalAlignment *)layoutHorizontalAlignment;
+ (MKUIWaterFlowLayoutConstraintParam)constraintParamWithLayoutDirection:(MKUILayoutConstraintDirection)layoutDirection layoutVerticalAlignment:(MKUILayoutConstraintVerticalAlignment)layoutVerticalAlignment layoutHorizontalAlignment:(MKUILayoutConstraintHorizontalAlignment)layoutHorizontalAlignment;
@end
NS_ASSUME_NONNULL_END

/**
 *
 以下为layoutDirection,layoutVerticalAlignment,layoutHorizontalAlignment的18种组合:
 
 MKUIWaterFlowLayoutConstraintParam_H_C_C
 layoutDirection = MKUILayoutConstraintDirectionHorizontal;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentCenter;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentCenter;
 :
 __________
|                        |
|           B           |
|    A  A B C C    |
|           B           |
|                        |
|              E        |
|       D D E        |
|              E        |
|____________|
 
 MKUIWaterFlowLayoutConstraintParam_H_C_L
 layoutDirection = MKUILayoutConstraintDirectionHorizontal;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentCenter;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentLeft;
:
 _______
|                 |
|   B            |
|A B C C C |
|   B            |
|                 |
|    E           |
|D E           |
|    E           |
|________ |
 
 MKUIWaterFlowLayoutConstraintParam_H_C_R
 layoutDirection = MKUILayoutConstraintDirectionHorizontal;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentCenter;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentRight;
 :
 _________
|                     |
|               B    |
| C C C C B A|
|               B    |
|                     |
|               E    |
|               E D|
|               E    |
|__________ |
 
 MKUIWaterFlowLayoutConstraintParam_H_T_C
 layoutDirection = MKUILayoutConstraintDirectionHorizontal;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentTop;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentCenter;
 :
 _________
|   A A B C C  |
|         B C C  |
|         B          |
|                     |
|    D D D E    |
|               E    |
|               E    |
|                     |
|__________ |
 
 MKUIWaterFlowLayoutConstraintParam_H_T_L
 layoutDirection = MKUILayoutConstraintDirectionHorizontal;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentTop;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentLeft;
 :
 _________
|A B C C C C  |
|   B C C C C  |
|   B                |
|                     |
|D E               |
|    E               |
|    E               |
|                     |
|__________ |
 
 MKUIWaterFlowLayoutConstraintParam_H_T_R
 layoutDirection = MKUILayoutConstraintDirectionHorizontal;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentTop;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentRight;
 :
 _________
|    C C C B A|
|    C C C B A|
|               B   |
|                    |
|              E D|
|              E D|
|              E    |
|                    |
|__________|

 MKUIWaterFlowLayoutConstraintParam_H_B_L
 layoutDirection = MKUILayoutConstraintDirectionHorizontal;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentBottom;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentLeft;
 :
  _______
 |                 |
 |                 |
 |    B          |
 |    B C C   |
 |A  B C C   |
 |                 |
 |     E          |
 |     E          |
 |D_E_____|
 
 MKUIWaterFlowLayoutConstraintParam_H_B_C
 layoutDirection = MKUILayoutConstraintDirectionHorizontal;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentBottom;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentCenter;
 :
  _______________
 |                                   |
 |                                   |
 |                B                 |
 |                B C C C C  |
 | A A A A A B C C C C  |
 |                                   |
 |                       E          |
 |                       E          |
 |____D_D_D_E_____|
 
 MKUIWaterFlowLayoutConstraintParam_H_B_R
 layoutDirection = MKUILayoutConstraintDirectionHorizontal;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentBottom;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentRight;
 :
  _______________
 |                                   |
 |                                   |
 |                           B     |
 |                           B  A |
 | C C C C C C C  B  A |
 |                                   |
 |                          E      |
 |                          E       |
 |_____________E_D_|
 
 MKUIWaterFlowLayoutConstraintParam_V_C_C
 layoutDirection = MKUILayoutConstraintDirectionVertical;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentCenter;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentCenter;
 :
 _________
|    A               |
|    A          D   |
| BBB     EEE |
|    C         F    |
|__C_______|
 
 MKUIWaterFlowLayoutConstraintParam_V_C_L
 layoutDirection = MKUILayoutConstraintDirectionVertical;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentCenter;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentLeft;
 :
 ___________
| AA                    |
| AA        DD       |
| BBBB   EEE     |
| C          F          |
| C___________|
 
 MKUIWaterFlowLayoutConstraintParam_V_C_R
 layoutDirection = MKUILayoutConstraintDirectionVertical;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentCenter;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentRight;
 :
 ____________
|          AA             |
|          AA       DD |
|     BBBB     EEE |
|           C         F  |
|_____C_______|

 
 MKUIWaterFlowLayoutConstraintParam_V_T_C
 layoutDirection = MKUILayoutConstraintDirectionVertical;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentTop;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentCenter;
 :
 _________
|    A          D   |
|    A          D   |
| BBB     EEE |
|    C              |
|__________|
 
 
 MKUIWaterFlowLayoutConstraintParam_V_T_L
 layoutDirection = MKUILayoutConstraintDirectionVertical;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentTop;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentLeft;
 :
 __________
| AA        D         |
| AA        D         |
| BBBB  EEE     |
| C                     |
|____________|

 
 MKUIWaterFlowLayoutConstraintParam_V_T_R
 layoutDirection = MKUILayoutConstraintDirectionVertical;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentTop;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentRight;
 :
 __________
|         AA        D|
|         AA        D|
|     BBBB   EEE|
|           C           |
|____________|
 
 
 MKUIWaterFlowLayoutConstraintParam_V_B_C
 layoutDirection = MKUILayoutConstraintDirectionVertical;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentBottom;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentCenter;
 :
 
 _________
|                      |
|    C               |
|    C          E   |
|  BBB       E   |
|__A___DDD |
 
 
 MKUIWaterFlowLayoutConstraintParam_V_B_L
 layoutDirection = MKUILayoutConstraintDirectionVertical;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentBottom;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentLeft;
 :
 ___________
|                          |
|C                        |
|C           E          |
|BBB      E          |
|A_____DDD __|
 
 MKUIWaterFlowLayoutConstraintParam_V_B_R
 layoutDirection = MKUILayoutConstraintDirectionVertical;
 layoutVerticalAlignment = MKUILayoutConstraintVerticalAlignmentBottom;
 layoutHorizontalAlignment = MKUILayoutConstraintHorizontalAlignmentRight;
 :
 ___________
|                           |
|         C               |
|         C             E|
|     BBB            E|
| ____A___DDD |
 */
